package org.sergiy.metawidget;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Factory;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.faces.FacesMessages;
import org.jboss.seam.international.StatusMessage.Severity;

import org.sergiy.forecast.WeatherService;
import org.sergiy.forecast.Forecast;
import org.sergiy.forecast.WeatherServiceException;

/**
 * JSF bean that manages forecasts
 *  
 * @author Sergiy Litsenko
 *
 */

@Name("forecaster")
@Scope(ScopeType.SESSION)
public class Forecaster implements Serializable  {
	private static final long serialVersionUID = 8086409669650675922L;
	
	// logger
	protected Log log = LogFactory.getLog (this.getClass());
	
	@In (value="forecastManager", create=true, required=false)
	WeatherService manager;

	// name of location to get forecast
	String searchLocation = "Sydney";
	

	@Out (value="todayForecast", required=false)
	Forecast  todayForecast;
	
	@Out (value="weeklyForecast", required=false)
	List<Forecast>  weeklyForecast;

	// search last updated
	Date lastUpdated = new Date();
	
	/**
	 * Constructor
	 */
	public Forecaster () {
	}
	
	/**
	 * Search forecast
	 */
	public void search() {
		try {
			// clear messages
			//FacesMessages.instance().clear();
			
			// debug
			if (log.isDebugEnabled()) {
				log.debug(String.format("Searching forecasts for the location: '%1$s'", searchLocation));
			}
			
			// do search
			if (searchLocation != null && manager != null) {
				// debug
				if (log.isDebugEnabled()) {
					log.debug(String.format("Searching weekly forecast for the location: '%1$s'", searchLocation));
				}
				
				// get for entire week
				weeklyForecast = manager.getWeeklyForecast(searchLocation);

				// search last updated
				lastUpdated = new Date();

				// debug
				if (log.isDebugEnabled()) {
					log.debug(String.format("Weekly forecast received on %2$s for the location: '%1$s'", searchLocation, lastUpdated));
					log.debug(String.format("Searching today's forecast for the location: '%1$s'", searchLocation));
				}
				
				// get for today
				//todayForecast = manager.getForecast(searchLocation);
				
				// get the first one
				todayForecast = weeklyForecast != null && !weeklyForecast.isEmpty()? weeklyForecast.get(0) : null;
				// remove from weekly forecast
				if (todayForecast != null) {
					weeklyForecast.remove(0);
				}
				// debug
				if (log.isDebugEnabled()) {
					log.debug(String.format("Today's forecast for the location: '%1$s' - %2$s", searchLocation, todayForecast));
				}
				
				// notify
				//FacesMessages.instance().add(Severity.INFO, "Last Updated on {0,date,dd-MM-yyyy hh:mm}", lastUpdated);
			} else {
				log.warn(String.format("The Weather Service manager: %1$s or search location: %2$s unavailable", manager, searchLocation));
			}
		} catch (WeatherServiceException e) {
			// log error
			log.error(String.format("Unable to get forecast for %1$s", searchLocation), e);
			
			// handle error
			//FacesMessages.instance().add(Severity.ERROR, "Unable to get forecast for {0} - {1}!", searchLocation, e.getMessage());
		}
	}
	
	/**
	 * @return the searchLocation
	 */
	public String getSearchLocation() {
		return searchLocation;
	}

	
	/**
	 * @param searchLocation the searchLocation to set
	 */
	public void setSearchLocation(String searchLocation) {
		this.searchLocation = searchLocation;
	}

	/**
	 * @return the todayForecast
	 */
	public Forecast getTodayForecast() {
		return todayForecast;
	}

	/**
	 * @return the weeklyForecast
	 */
	public List<Forecast> getWeeklyForecast() {
		return weeklyForecast;
	}

	/**
	 * @return the lastUpdated
	 */
	public Date getLastUpdated() {
		return lastUpdated;
	}

}
